/*****************************************************************************
*
*  PROJECT:     Multi Theft Auto v1.2
*  LICENSE:     See LICENSE in the top level directory
*  FILE:        FileSystem/src/fsinternal/CFileSystem.internal.nativeimpl.hxx
*  PURPOSE:     Native implementation utilities to share across files
*
*  Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#ifndef _FILESYSTEM_NATIVE_SHARED_IMPLEMENTATION_PRIVATE_
#define _FILESYSTEM_NATIVE_SHARED_IMPLEMENTATION_PRIVATE_

#ifdef _WIN32

inline HANDLE _FileWin32_OpenDirectoryHandle( const filePath& absPath, eDirOpenFlags flags = DIR_FLAG_NONE )
{
    HANDLE dir = INVALID_HANDLE_VALUE;

    // Determine the share mode.
    DWORD dwShareMode = 0;

    if ( ( flags & DIR_FLAG_EXCLUSIVE ) == 0 )
    {
        dwShareMode |= ( FILE_SHARE_READ | FILE_SHARE_WRITE );
    }

    DWORD accessMode = 0;

    if ( ( flags & DIR_FLAG_NO_READ ) == 0 )
    {
        accessMode |= GENERIC_READ;
    }

    if ( ( flags & DIR_FLAG_WRITABLE ) != 0 )
    {
        accessMode |= GENERIC_WRITE;
    }

    if ( const char *sysPath = absPath.c_str() )
    {
        dir = CreateFileA( sysPath, accessMode, dwShareMode, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
    }
    else if ( const wchar_t *sysPath = absPath.w_str() )
    {
        dir = CreateFileW( sysPath, accessMode, dwShareMode, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
    }

    return dir;
}

// Getting file information on the Windows platform reliably.
static bool _FileWin32_GetFileInformation( HANDLE fileHandle, struct stat *pFileStats )
{
    BY_HANDLE_FILE_INFORMATION info;

    if ( GetFileInformationByHandle( fileHandle, &info ) == FALSE )
        return false;

    pFileStats->st_size = info.nFileSizeLow;
    pFileStats->st_dev = info.nFileIndexLow;
    pFileStats->st_atime = info.ftLastAccessTime.dwLowDateTime;
    pFileStats->st_ctime = info.ftCreationTime.dwLowDateTime;
    pFileStats->st_mtime = info.ftLastWriteTime.dwLowDateTime;
    pFileStats->st_dev = info.dwVolumeSerialNumber;
    pFileStats->st_mode = 0;
    pFileStats->st_nlink = (unsigned short)info.nNumberOfLinks;
    pFileStats->st_rdev = 0;
    pFileStats->st_gid = 0;
    pFileStats->st_ino = 0;
    pFileStats->st_uid = 0;
    return true;
}

// Helper for file paths.
static bool _FileWin32_GetFileInformationByPath( const filePath& path, struct stat *statsOut )
{
    HANDLE fileHandle = _FileWin32_OpenDirectoryHandle( path, DIR_FLAG_NO_READ );

    bool success = false;

    if ( fileHandle != INVALID_HANDLE_VALUE )
    {
        success = _FileWin32_GetFileInformation( fileHandle, statsOut );

        CloseHandle( fileHandle );
    }

    return success;
}

#endif

#endif //_FILESYSTEM_NATIVE_SHARED_IMPLEMENTATION_PRIVATE_